﻿// ------------------------------------------------------------------------
// 版权信息
// 版权归重庆虫儿飞科技有限公司所有。
// 所有权利保留。
// 官方网站：https://netokit.com
// 许可证信息
// Neto.Kit 项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
// 
// 使用条款
// 使用本代码应遵守相关法律法规和许可证的要求。
// 
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
// 
// 其他重要信息
// Neto.Kit 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// 有关 Neto.Kit 项目的其他详细信息，请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
// 
// 更多信息
// 请访问 https://netokit.com 获取更多关于 Neto.Kit 项目的许可证和版权信息。
// ------------------------------------------------------------------------

namespace Neto.Db.SqlSugar;

/// <summary>
///     sqlsugar 缓存的仓储
///     警告：小数据量的表才用，否则可能会造成意想不到的问题
/// </summary>
/// <typeparam name="TEntity"></typeparam>
[SuppressSniffer]
public class SqlSugarCacheRepository2<TEntity> where TEntity : class, new()
{
    //public SqlSugarCacheRepository()
    //{
    //}

    /// <summary>
    ///     缓存Key
    /// </summary>
    public readonly string cacheKey;

    /// <summary>
    ///     更新忽略的字段
    /// </summary>
    private readonly string[] UpdateIgnoreColumns = { "CreatorUserId", "CreatorUserName", "CreationTime" };

    public SqlSugarCacheRepository2(ISqlSugarClient db = null)
    {
        cacheKey = $"Table_{typeof(TEntity).Name}";

        if (db == null)
            _db = App.GetService<ISqlSugarClient>();
        else
            _db = db;
        Ado = _db.Ado;
        RefreshCache();

        //base.Context = context;//ioc注入的对象
        // base.Context=DbScoped.SugarScope; SqlSugar.Ioc这样写
        // base.Context=DbHelper.GetDbInstance()当然也可以手动去赋值
    }

    /// <summary>
    ///     初始化 SqlSugar 客户端
    /// </summary>
    public ISqlSugarClient _db { get; set; }

    /// <summary>
    ///     原生 Ado 对象
    /// </summary>
    public virtual IAdo Ado { get; }

    public ITenant AsTenant()
    {
        return _db as ITenant;
    }

    public ISqlSugarClient AsSugarClient()
    {
        return _db;
    }

    /// <summary>
    ///     获取全部集合
    /// </summary>
    /// <returns></returns>
    public List<TEntity> GetList()
    {
        return GetListAsync().GetAwaiter().GetResult();
    }

    /// <summary>
    ///     获取全部集合
    /// </summary>
    /// <returns></returns>
    public async Task<List<TEntity>> GetListAsync()
    {
        var datas = await CacheX.GetAsync<List<TEntity>>(cacheKey);
        if (datas != null && datas.Any())
            return datas;
        return await RefreshCacheAsync();
    }

    #region Base

    /// <summary>
    ///     改变类型
    /// </summary>
    /// <typeparam name="ChangeType"></typeparam>
    /// <returns></returns>
    public SimpleClient<ChangeType> Change<ChangeType>() where ChangeType : class, new()
    {
        return _db.GetSimpleClient<ChangeType>();
    }

    /// <summary>
    ///     改变仓储
    /// </summary>
    /// <typeparam name="RepositoryType"></typeparam>
    /// <returns></returns>
    public RepositoryType ChangeRepository<RepositoryType>() where RepositoryType : ISugarRepository
    {
        var typeFromHandle = typeof(RepositoryType);
        object[] args = new string[1];
        var obj = Activator.CreateInstance(typeFromHandle, args);
        var result = (RepositoryType)obj;
        if (result.Context == null) result.Context = _db;

        return result;
    }

    public ISugarQueryable<TEntity> AsQueryable()
    {
        return _db.Queryable<TEntity>();
    }

    public IInsertable<TEntity> AsInsertable(TEntity insertObj)
    {
        return _db.Insertable(insertObj);
    }

    public IInsertable<TEntity> AsInsertable(TEntity[] insertObjs)
    {
        return _db.Insertable(insertObjs);
    }

    public IInsertable<TEntity> AsInsertable(List<TEntity> insertObjs)
    {
        return _db.Insertable(insertObjs);
    }

    public IUpdateable<TEntity> AsUpdateable(TEntity updateObj)
    {
        return _db.Updateable(updateObj);
    }

    public IUpdateable<TEntity> AsUpdateable(TEntity[] updateObjs)
    {
        return _db.Updateable(updateObjs);
    }

    public IUpdateable<TEntity> AsUpdateable(List<TEntity> updateObjs)
    {
        return _db.Updateable(updateObjs);
    }

    public IUpdateable<TEntity> AsUpdateable()
    {
        return _db.Updateable<TEntity>();
    }

    public IDeleteable<TEntity> AsDeleteable()
    {
        return _db.Deleteable<TEntity>();
    }

    #endregion Base

    #region Cache

    //public bool IsCache => CacheX.Exist(cacheKey);

    /// <summary>
    ///     缓存数据
    /// </summary>
    public List<TEntity> CacheDatas => GetList();

    ///// <summary>
    ///// 获取缓存数据
    ///// </summary>
    ///// <returns></returns>
    //public virtual async Task<List<TEntity>> GetCacheDatas()
    //{
    //}

    /// <summary>
    ///     刷新缓存
    /// </summary>
    /// <returns></returns>
    public List<TEntity> RefreshCache()
    {
        return RefreshCacheAsync().GetAwaiter().GetResult();
    }

    /// <summary>
    ///     刷新缓存
    /// </summary>
    /// <returns></returns>
    public virtual async Task<List<TEntity>> RefreshCacheAsync()
    {
        var datas = await _db.Queryable<TEntity>().ToListAsync();
        await datas.SetCacheAsync(cacheKey);
        return datas;
    }

    #endregion Cache

    #region 同步

    /// <summary>
    ///     新增一条
    /// </summary>
    /// <param name="insertObj"></param>
    /// <returns></returns>
    public virtual bool Insert(TEntity insertObj)
    {
        var state = _db.Insertable(insertObj).ExecuteCommand() > 0;
        RefreshCacheAsync().GetAwaiter().GetResult();
        return state;
    }

    /// <summary>
    ///     新增或更新一条
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public virtual bool InsertOrUpdate(TEntity data)
    {
        var state = _db.Storageable(data)
            .ExecuteCommand() > 0;
        RefreshCacheAsync().GetAwaiter().GetResult();
        return state;
    }

    /// <summary>
    ///     新增或更新多条
    /// </summary>
    /// <param name="datas"></param>
    /// <returns></returns>
    public virtual bool InsertOrUpdate(List<TEntity> datas)
    {
        var state = _db.Storageable(datas)
            .ExecuteCommand() > 0;
        RefreshCacheAsync().GetAwaiter().GetResult();
        return state;
    }

    /// <summary>
    ///     新增一条并返回自增ID
    /// </summary>
    /// <param name="insertObj"></param>
    /// <returns>int型的自增ID</returns>
    public virtual int InsertReturnIdentity(TEntity insertObj)
    {
        var count = _db.Insertable(insertObj).ExecuteReturnIdentity();
        RefreshCacheAsync().GetAwaiter().GetResult();
        return count;
    }

    /// <summary>
    ///     新增一条并返回自增ID
    /// </summary>
    /// <param name="insertObj"></param>
    /// <returns>long型的自增ID</returns>
    public virtual long InsertReturnBigIdentity(TEntity insertObj)
    {
        var id = _db.Insertable(insertObj).ExecuteReturnBigIdentity();
        RefreshCacheAsync().GetAwaiter().GetResult();
        return id;
    }

    /// <summary>
    ///     新增一条并返回雪花ID
    /// </summary>
    /// <param name="insertObj"></param>
    /// <returns></returns>
    public virtual long InsertReturnSnowflakeId(TEntity insertObj)
    {
        var id = _db.Insertable(insertObj).ExecuteReturnSnowflakeId();
        RefreshCacheAsync().GetAwaiter().GetResult();
        return id;
    }

    /// <summary>
    ///     新增多条 返回雪花ID集合
    /// </summary>
    /// <param name="insertObjs"></param>
    /// <returns></returns>
    public virtual List<long> InsertReturnSnowflakeId(List<TEntity> insertObjs)
    {
        var listid = _db.Insertable(insertObjs).ExecuteReturnSnowflakeIdList();
        RefreshCacheAsync().GetAwaiter().GetResult();
        return listid;
    }

    /// <summary>
    ///     新增多条
    /// </summary>
    /// <param name="insertObjs"></param>
    /// <returns></returns>
    public virtual bool InsertRange(List<TEntity> insertObjs)
    {
        var state = _db.Insertable(insertObjs).ExecuteCommand() > 0;
        RefreshCacheAsync().GetAwaiter().GetResult();
        return state;
    }

    /// <summary>
    ///     更新一条
    /// </summary>
    /// <param name="updateObj"></param>
    /// <returns></returns>
    public virtual bool Update(TEntity updateObj)
    {
        var state = _db.Updateable(updateObj)
            .IgnoreColumns(UpdateIgnoreColumns)
            .ExecuteCommand() > 0;
        RefreshCacheAsync().GetAwaiter().GetResult();
        return state;
    }

    /// <summary>
    ///     更新多条
    /// </summary>
    /// <param name="updateObjs"></param>
    /// <returns></returns>
    public virtual bool UpdateRange(List<TEntity> updateObjs)
    {
        var state = _db.Updateable(updateObjs)
            .IgnoreColumns(UpdateIgnoreColumns)
            .ExecuteCommand() > 0;
        RefreshCacheAsync().GetAwaiter().GetResult();
        return state;
    }

    /// <summary>
    ///     按条件更新多条
    /// </summary>
    /// <param name="columns"></param>
    /// <param name="whereExpression">表达式</param>
    /// <returns></returns>
    public virtual bool Update(Expression<Func<TEntity, TEntity>> columns,
        Expression<Func<TEntity, bool>> whereExpression)
    {
        var state = _db.Updateable<TEntity>()
            .SetColumns(columns)
            .Where(whereExpression).ExecuteCommand() > 0;
        RefreshCacheAsync().GetAwaiter().GetResult();
        return state;
    }

    /// <summary>
    ///     删除
    /// </summary>
    /// <param name="deleteObj"></param>
    /// <returns></returns>
    public virtual bool Delete(TEntity deleteObj)
    {
        var state = _db.Deleteable<TEntity>().Where(deleteObj).ExecuteCommand() > 0;
        RefreshCacheAsync().GetAwaiter().GetResult();
        return state;
    }

    /// <summary>
    ///     删除多条
    /// </summary>
    /// <param name="deleteObjs"></param>
    /// <returns></returns>
    public virtual bool Delete(List<TEntity> deleteObjs)
    {
        var state = _db.Deleteable<TEntity>().Where(deleteObjs).ExecuteCommand() > 0;
        RefreshCacheAsync().GetAwaiter().GetResult();
        return state;
    }

    /// <summary>
    ///     按条件删除
    /// </summary>
    /// <param name="whereExpression"></param>
    /// <returns></returns>
    public virtual bool Delete(Expression<Func<TEntity, bool>> whereExpression)
    {
        var state = _db.Deleteable<TEntity>().Where(whereExpression).ExecuteCommand() > 0;
        RefreshCacheAsync().GetAwaiter().GetResult();
        return state;
    }

    /// <summary>
    ///     按ID删除一条
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public virtual bool DeleteById(long id)
    {
        var state = _db.Deleteable<TEntity>().In(id).ExecuteCommand() > 0;
        RefreshCacheAsync().GetAwaiter().GetResult();
        return state;
    }

    /// <summary>
    ///     按ID集合删除多条
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public virtual bool DeleteByIds(List<long> ids)
    {
        var state = _db.Deleteable<TEntity>().In(ids).ExecuteCommand() > 0;
        RefreshCacheAsync().GetAwaiter().GetResult();
        return state;
    }

    #endregion 同步

    #region 异步

    /// <summary>
    ///     新增一条并返回雪花ID
    /// </summary>
    /// <param name="insertObj"></param>
    /// <returns></returns>
    public virtual async Task<long> InsertReturnSnowflakeIdAsync(TEntity insertObj)
    {
        var id = await _db.Insertable(insertObj).ExecuteReturnSnowflakeIdAsync();
        await RefreshCacheAsync();
        return id;
    }

    /// <summary>
    ///     新增多条 返回雪花ID集合
    /// </summary>
    /// <param name="insertObjs"></param>
    /// <returns></returns>
    public virtual async Task<List<long>> InsertReturnSnowflakeIdAsync(List<TEntity> insertObjs)
    {
        var listid = await _db.Insertable(insertObjs).ExecuteReturnSnowflakeIdListAsync();
        await RefreshCacheAsync();
        return listid;
    }

    /// <summary>
    ///     新增或更新一条
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public virtual async Task<bool> InsertOrUpdateAsync(TEntity data)
    {
        var state = await _db.Storageable(data).ExecuteCommandAsync() > 0;
        await RefreshCacheAsync();
        return state;
    }

    /// <summary>
    ///     新增或更新多条
    /// </summary>
    /// <param name="datas"></param>
    /// <returns></returns>
    public virtual async Task<bool> InsertOrUpdateAsync(List<TEntity> datas)
    {
        var state = await _db.Storageable(datas).ExecuteCommandAsync() > 0;
        await RefreshCacheAsync();
        return state;
    }

    /// <summary>
    ///     新增一条
    /// </summary>
    /// <param name="insertObj"></param>
    /// <returns></returns>
    public virtual async Task<bool> InsertAsync(TEntity insertObj)
    {
        var state = await _db.Insertable(insertObj).ExecuteCommandAsync() > 0;
        await RefreshCacheAsync();
        return state;
    }

    /// <summary>
    ///     新增一条并返回自增ID
    /// </summary>
    /// <param name="insertObj"></param>
    /// <returns>int型的自增ID</returns>
    public virtual async Task<int> InsertReturnIdentityAsync(TEntity insertObj)
    {
        var id = await _db.Insertable(insertObj).ExecuteReturnIdentityAsync();
        await RefreshCacheAsync();
        return id;
    }

    /// <summary>
    ///     新增一条并返回自增ID
    /// </summary>
    /// <param name="insertObj"></param>
    /// <returns>long型的自增ID</returns>
    public virtual async Task<long> InsertReturnBigIdentityAsync(TEntity insertObj)
    {
        var state = await _db.Insertable(insertObj).ExecuteReturnBigIdentityAsync();
        await RefreshCacheAsync();
        return state;
    }

    /// <summary>
    ///     新增多条
    /// </summary>
    /// <param name="insertObjs"></param>
    /// <returns></returns>
    public virtual async Task<bool> InsertRangeAsync(List<TEntity> insertObjs)
    {
        var state = await _db.Insertable(insertObjs).ExecuteCommandAsync() > 0;
        await RefreshCacheAsync();
        return state;
    }

    /// <summary>
    ///     更新一条
    /// </summary>
    /// <param name="updateObj"></param>
    /// <returns></returns>
    public virtual async Task<bool> UpdateAsync(TEntity updateObj)
    {
        var state = await _db.Updateable(updateObj)
            .IgnoreColumns(UpdateIgnoreColumns)
            .ExecuteCommandAsync() > 0;
        await RefreshCacheAsync();
        return state;
    }

    /// <summary>
    ///     更新多条
    /// </summary>
    /// <param name="updateObjs"></param>
    /// <returns></returns>
    public virtual async Task<bool> UpdateRangeAsync(List<TEntity> updateObjs)
    {
        var state = await _db.Updateable(updateObjs)
            .IgnoreColumns(UpdateIgnoreColumns)
            .ExecuteCommandAsync() > 0;
        await RefreshCacheAsync();
        return state;
    }

    /// <summary>
    ///     按条件更新多条
    /// </summary>
    /// <param name="columns"></param>
    /// <param name="whereExpression"></param>
    /// <returns></returns>
    public virtual async Task<bool> UpdateAsync(Expression<Func<TEntity, TEntity>> columns,
        Expression<Func<TEntity, bool>> whereExpression)
    {
        var state = await _db.Updateable<TEntity>()
            .SetColumns(columns)
            .Where(whereExpression).ExecuteCommandAsync() > 0;
        await RefreshCacheAsync();
        return state;
    }

    /// <summary>
    ///     删除一条
    /// </summary>
    /// <param name="deleteObj"></param>
    /// <returns></returns>
    public virtual async Task<bool> DeleteAsync(TEntity deleteObj)
    {
        var state = await _db.Deleteable<TEntity>().Where(deleteObj).ExecuteCommandAsync() > 0;
        await RefreshCacheAsync();
        return state;
    }

    /// <summary>
    ///     删除多条
    /// </summary>
    /// <param name="deleteObjs"></param>
    /// <returns></returns>
    public virtual async Task<bool> DeleteAsync(List<TEntity> deleteObjs)
    {
        var state = await _db.Deleteable<TEntity>().Where(deleteObjs).ExecuteCommandAsync() > 0;
        await RefreshCacheAsync();
        return state;
    }

    /// <summary>
    ///     根据条件删除
    /// </summary>
    /// <param name="whereExpression"></param>
    /// <returns></returns>
    public virtual async Task<bool> DeleteAsync(Expression<Func<TEntity, bool>> whereExpression)
    {
        var state = await _db.Deleteable<TEntity>().Where(whereExpression).ExecuteCommandAsync() > 0;
        await RefreshCacheAsync();
        return state;
    }

    /// <summary>
    ///     更加ID删除一条
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public virtual async Task<bool> DeleteByIdAsync(long id)
    {
        var state = await _db.Deleteable<TEntity>().In(id).ExecuteCommandAsync() > 0;
        await RefreshCacheAsync();
        return state;
    }

    /// <summary>
    ///     更加ID删除多条
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public virtual async Task<bool> DeleteByIdsAsync(List<long> ids)
    {
        var state = await _db.Deleteable<TEntity>().In(ids).ExecuteCommandAsync() > 0;
        await RefreshCacheAsync();
        return state;
    }

    /// <summary>
    ///     更加ID删除多条
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public virtual async Task<bool> DeleteByIdsAsync(List<int> ids)
    {
        var state = await _db.Deleteable<TEntity>().In(ids).ExecuteCommandAsync() > 0;
        await RefreshCacheAsync();
        return state;
    }

    #endregion 异步

    ///// <summary>
    ///// 扩展方法，自带方法不能满足的时候可以添加新方法
    ///// </summary>
    ///// <returns></returns>
    //public List<TEntity> CommQuery(string json)
    //{
    //    //base._db.Queryable<TEntity>().ToList();可以拿到SqlSugarClient 做复杂操作
    //    return null;
    //}
}